package cn.tj212.xiaoyin.common.util;

import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

public class EncryptUtil {
    public static String encodeByMD5(String source) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] results = md.digest(source.getBytes());
            String result = bytesToHex(results);
            return result.toUpperCase();
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalArgumentException();
        }
    }

    public static String bytesToHex(byte[] src) {
        StringBuilder stringBuilder = new StringBuilder();
        if (src == null || src.length <= 0)
            return null;
        for (int i = 0; i < src.length; i++) {
            int v = src[i] & 0xff;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString().toUpperCase();
    }

    public static String encryptSHA1(String content) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-1");
            digest.update(content.getBytes());
            byte[] messageDigest = digest.digest();
            //create hex string
            StringBuilder hexStr = new StringBuilder();
            for (int i = 0; i < messageDigest.length; i++) {
                String shaHex = Integer.toHexString(messageDigest[i] & 0xff);
                if (shaHex.length() < 2) {
                    hexStr.append(0);
                }
                hexStr.append(shaHex);
            }
            return hexStr.toString().toUpperCase();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 使用AES的CBC模式加密
     *
     * @param key  加密使用的秘钥
     * @param text 待加密的内容
     * @return 经过base64编码的密文
     */
    public static String encryptByAESWithCBC(byte[] key, byte[] text) {
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
            //使用CBC模式，需要指定初始化向量，可以增加加密算法的强度
            IvParameterSpec iv = new IvParameterSpec(key, 0, 16);
            cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);
            byte[] encrypted = cipher.doFinal(text);
            String base64Encrypted = new Base64().encodeToString(encrypted);
            return base64Encrypted;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 解码
     *
     * @param key
     * @param text
     * @return
     */
    public static byte[] decryptByAESWithCBC(byte[] key, byte[] text) {
        byte[] original = null;
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            //生成秘钥
            SecretKeySpec key_spec = new SecretKeySpec(key, "AES");
            //使用CBC模式，需要指定初始化向量，可以增加加密算法的强度
            IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(key, 0, 16));
            cipher.init(Cipher.DECRYPT_MODE, key_spec, iv);
            original = cipher.doFinal(text);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return original;
    }
}
